package com.redis_company;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

// 与 redis 进行交互
public class Main {
    static Socket socket;
    static PrintWriter writer; // 按行读
    static BufferedReader reader; // 按行写

    public static void main(String[] args) throws IOException {
        try {
            // 1. 与 redis 建立 连接，利用 socket
            String host = "192.168.159.128";
            int port = 6379;
            socket = new Socket(host, port);

            // 2. 获取 socket 的输入流，输出流
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));

            // TODO 3. 发送测试请求
            // 3.1 获取授权 auth 123

            sendRequest("set","name2","小兰");

            // TODO 4. 解析响应
            Object obj = handleResponse();
            System.out.println("obj : " + obj);

            sendRequest("get","name2");
            Object obj2 = handleResponse();
            System.out.println("obj2 : " + obj2);

            sendRequest("mget","name","name2");
            Object obj3 = handleResponse();
            System.out.println("obj3 : " + obj3);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5. 释放连接
            if (reader != null) {
                reader.close();
            }
            if (writer != null) {
                writer.close();
            }
            if (socket != null) {
                socket.close();
            }
        }

    }

    private static Object handleResponse() throws IOException {
        // 读取首字节，判断数据类型标识
        int prefix = reader.read();
        switch (prefix) {
            case '+': // 单行
                return reader.readLine();
            case '-': // 异常
                throw new RuntimeException(reader.readLine());
            case ':': // 数字
                return Long.parseLong(reader.readLine());
            case '$': // 多行
                int len = Integer.parseInt(reader.readLine());
                if (len == -1) {
                    return null;
                } else if (len == 0) {
                    return "";
                } else {
                    // 假设没有特殊字符，直接偷懒读一行
                    return reader.readLine();
                }
            case '*':
                return readBulkString();
            default:
                throw new RuntimeException("错误的数据格式！");
        }
    }

    private static Object readBulkString() throws IOException {
        // 获取数组大小
        int len = Integer.parseInt(reader.readLine());
        if (len <= 0) {
            return null;
        } else {
            // 依次遍历读取元素
            List<Object> list = new ArrayList<>(len);
            for (int i = 0; i < len; i++) {
                handleResponse();
                list.add(handleResponse());
            }
            return list;
        }
    }

    private static void sendRequest(String ... args) {
        // set name 小明
//        String input = "*3\r\n$3\r\nset\r\n$4\r\nname\r\n$6\r\n小明\r\n";
//        writer.print(input);
        writer.println("*" + args.length);
        for (String arg : args) {
            writer.println("$" + arg.getBytes(StandardCharsets.UTF_8).length);
            writer.println(arg);
        }
        writer.flush();
    }
}
